﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PHPDecoder
{
    class Node
    {
        public char aChar;
        public Dictionary<char, Node> aMap = null;
        public Node pFailureNode = null;
        public Node parent = null;
        public bool bResult = false;
        public string Prefix;

        PHPKEYWORDS Result;
        
        public PHPKEYWORDS result
        {
            set
            {
                bResult = true;
                Result = value;
            }
            get { return Result; }
        }

        public Node(char c)
        {
            this.aChar = c;
            aMap = new Dictionary<char, Node>();
        }
        
    }

    class SuffixTrie
    {
        public Node root = null;
        public SuffixTrie()
        {
            root = new Node((char)0);
            root.pFailureNode = root;
        }

        public void AddString(String s, PHPKEYWORDS ReturnValue)
        {
            AddString(root, s, ReturnValue, 0);
        }
        private void AddString(Node n, String s, PHPKEYWORDS ReturnValue, int index)
        {

            if (index == s.Length)
            {
                n.Prefix = s;
                n.result = ReturnValue;
                return;
            }
            
            if (n.aMap.ContainsKey(s[index]))
            {
                int x = index + 1;
                AddString(n.aMap[s[index]], s, ReturnValue, x);
            }
            else
            {
                Node nn = new Node(s[index]);
                int x = index + 1;
                nn.Prefix = s.Substring(0, x);
                n.aMap.Add(s[index], nn);
                AddString(nn, s, ReturnValue, x);
            }
        }

        public void MakeFallFunction()
        {
            Queue<Node> queue = new Queue<Node>();
            queue.Enqueue(root);
            while (queue.Count != 0)
            {
                Node node = queue.Dequeue();
                foreach (Node nn in node.aMap.Values)
                {
                    queue.Enqueue(nn);
                }


                String s = node.Prefix;
                if (s == null) continue;
                Node n = root;
                for (int i = 1; i < s.Length; i++)
                {
                    n = Krok(n, s[i]);
                }
                node.pFailureNode = n;
            }

        }
        
        private void Enqueue(Node n, Queue<Node> q)
        {
        }

        public Node Krok(Node n, char c)
        {
            if (n == root) return n.aMap.ContainsKey(c) ? root.aMap[c] : root;

            return (n.aMap.ContainsKey(c)) ? n.aMap[c] : Krok(n.pFailureNode, c);
        }
    }
}